source("utils.R")
theme_set(theme_minimal())Irregular Lattices
Dependencies
Until now we have considered the cells to be represented in a point pattern. However, as cells have a shape and area, this might be an oversimplification in some cases. Alternatively, we can rely on the segmentation of indvidual cells that are available for various datasets. The outline of each cell is represented by a polygon and the collection of all cells can be seen as an irregular lattice. Unlike a regular lattice (the representation of spot based spatial tanscriptomics data) the sample areas in an irregular lattice can have different sizes and are not reugularly distributed over the sample space.
For this representation of the cells we will rely on the SpatialFeatureExperiment package. For preprocessing of the dataset we refer the reader to the vignette of the voyager package.
(sfe <- HeNSCLCData())class: SpatialFeatureExperiment
dim: 980 100290
metadata(0):
assays(1): counts
rownames(980): AATK ABL1 ... NegPrb22 NegPrb23
rowData names(3): means vars cv2
colnames(100290): 1_1 1_2 ... 30_4759 30_4760
colData names(17): Area AspectRatio ... nCounts nGenes
reducedDimNames(0):
mainExpName: NULL
altExpNames(0):
spatialCoords names(2) : CenterX_global_px CenterY_global_px
imgData names(1): sample_id
unit: full_res_image_pixels
Geometries:
colGeometries: centroids (POINT), cellSeg (POLYGON)
Graphs:
sample01:
# Empty cells
colData(sfe)$is_empty <- colData(sfe)$nCounts < 1
# Select negative control probes
neg_inds <- str_detect(rownames(sfe), "^NegPrb")
# Number of negative control probes
sum(neg_inds)[1] 20
colData(sfe)$prop_neg <- colSums(counts(sfe)[neg_inds,])/colData(sfe)$nCounts
# Remove low quality cells
(sfe <- sfe[,!sfe$is_empty & sfe$prop_neg < 0.1])class: SpatialFeatureExperiment
dim: 980 100095
metadata(0):
assays(1): counts
rownames(980): AATK ABL1 ... NegPrb22 NegPrb23
rowData names(3): means vars cv2
colnames(100095): 1_1 1_2 ... 30_4759 30_4760
colData names(19): Area AspectRatio ... is_empty prop_neg
reducedDimNames(0):
mainExpName: NULL
altExpNames(0):
spatialCoords names(2) : CenterX_global_px CenterY_global_px
imgData names(1): sample_id
unit: full_res_image_pixels
Geometries:
colGeometries: centroids (POINT), cellSeg (POLYGON)
Graphs:
sample01:
# Calculate count stats
rowData(sfe)$means <- rowMeans(counts(sfe))
rowData(sfe)$vars <- rowVars(counts(sfe))
rowData(sfe)$is_neg <- neg_inds
# log Counts
sfe <- logNormCounts(sfe)In this vignette we will show the metrics related to two marker genes, KRT17 which is a marker of basal cells and TAGLN which is a marker of smooth muscle cells.
plotSpatialFeature(sfe, c("KRT17"),
colGeometryName = "centroids", ncol = 2, scattermore = TRUE) +
theme_void()plotSpatialFeature(sfe, c("TAGLN"),
colGeometryName = "centroids", ncol = 2, scattermore = TRUE) +
theme_void()Irregular lattice and neighbourhood matrix
In general a spatial autocorrelation measure has the follwing elements a function \(f(x_i, x_j)\) of the values at locations \(x_i\) and \(x_j\) and a weights matrix \(w_{ij}\). The function \(f\) relates the values \(x_i\) and \(x_j\) and the weights matrix \(w_{ij}\) relates the locations of \(x_i\) and \(x_j\). If \(x_i\) and \(x_j\) are not neighbours the element of the weights matrix is 0. The general the spatial autocorrelation has the of a double sum over all locations \(\sum_i \sum_j f(x_i,x_j) w_{ij}\).
The analysis techniques rely on the a neighborhood matrix, which is a matrix that indicates which cells are neighbors. In the case of the regular lattice, the calculation of the neighborhood matrix is rather straightforward. In the case of the irregular lattice it can be more complicated as the reconstruction of the cells is often not perfect.
Neighbourhood matrix
One of the challenges when working with irregular lattice data is the construction of a neighbourhood graph. The main question is, what to consider as neighbours, as this will affect downstream analyses. Various methods exist to create neighbours, such as contiguitiy based neighbours, graph-based neighbours, distance based neighbours or higher order neighbours. The segmentation of individual cells in notoriously difficult and often the segmentation is not perfect. Therefore we cannot simply rely on neighbours based on the segementation results and the construction of contiguitiy based neighbours is therefore not ideal, also as it would neglect the influence of more distant neighbours.s
References for the construction of the neighbourhood matrix: * https://r-spatial.github.io/spdep/articles/nb.html * https://r-spatial.org/book/14-Areal.html * https://pachterlab.github.io/voyager/articles/vig4_cosmx.html#data-normalization * Getis, Arthur. 2009. “Spatial Weights Matrices.” Geogr. Anal. 41 (4): 404–10. * Zuur, A. F., Ieno, E. N., Smith, G. M., Saveliev, A. A., Mukharamova, S. S., & Zuur, A. F. (2007). Analysis and modelling of lattice data. Analysing Ecological Data, 321-339.
In the following we will use the k-nearest neighbours approach from voyager which relies on spdep. The approach and the number \(k\) is somewhat arbritary.
Thought: if we assume non perfect segmentation we could basically calculate the same statistics also on point pattern derived datasets. We would also use a k-nearest neighbours approach in a “point pattern” dataset. The centroids of the cells as a proxy for the spatial location.
Is there a good methods to dermine a good neighbourhood matrix?
Point pattern as a “event based” dataset, lattice data an “observation” based dataset.
colGraph(sfe, "knn5") <- findSpatialNeighbors(sfe, method = "knearneigh",
dist_type = "idw", k = 5,
style = "W")Global Methods
Global methods give us an overview over the entire study are. The gobal measures summarize the spatial distribution of the cells in a single value. The most common global measures are the Moran’s I and Geary’s C coefficients. These coefficients are based on the spatial weights matrix and the values of the variable of interest.
Global Moran’s I coefficient
The global Moran’s I coefficient is a measure of spatial autocorrelation. It is defined as
\[I = \frac{n}{\sum_i\sum_j w_{ij}} \frac{\sum_i\sum_j w_{ij}(y_i - \hat{y})(y_j - \hat{y})}{\sum_i (y_i - \hat{y})^2}\]
where \(y_i\) is the value of the variable of interest for location \(i\), \(\hat{y}\) is the mean of \(y_i\) and \(w_{ij}\) is the spatial weight between locations \(i\) and \(j\). This value is close to \(0\) for large \(n\). A value higher than \(\mathbb{E}(I) = -1/(n-1)\) indicates spatial auto-correlation. Negative values indicate negative auto-correlation.
Implementation using voyager
calculateMoransI(sfe,
features = c("KRT17", "TAGLN"),
colGraphName = "knn5",
exprs_values = "logcounts"
)DataFrame with 2 rows and 2 columns
moran K
<numeric> <numeric>
KRT17 0.643987 5.09219
TAGLN 0.262379 6.55766
sfe <- runUnivariate(sfe,
features = c("KRT17", "TAGLN"),
colGraphName = "knn5",
exprs_values = "logcounts",
type = "moran.mc",
nsim = 200)
res <- rowData(sfe)[c("KRT17", "TAGLN"),]
#value of the metric
res$moran.mc_statistic_sample01[1] 0.6439874 0.2623794
#p-value
res$moran.mc_p.value_sample01[1] 0.004975124 0.004975124
Implementation using spdep
#create nearest neighbours weights
weights_neighbourhoods <- colGraph(sfe, "knn5")
spdep::moran.test(x = logcounts(sfe)["KRT17",],
listw = weights_neighbourhoods,
randomisation = TRUE)
Moran I test under randomisation
data: logcounts(sfe)["KRT17", ]
weights: weights_neighbourhoods
Moran I statistic standard deviate = 319.35, p-value < 2.2e-16
alternative hypothesis: greater
sample estimates:
Moran I statistic Expectation Variance
6.439874e-01 -9.990609e-06 4.066523e-06
spdep::moran.test(x = logcounts(sfe)["TAGLN",],
listw = weights_neighbourhoods,
randomisation = TRUE)
Moran I test under randomisation
data: logcounts(sfe)["TAGLN", ]
weights: weights_neighbourhoods
Moran I statistic standard deviate = 130.12, p-value < 2.2e-16
alternative hypothesis: greater
sample estimates:
Moran I statistic Expectation Variance
2.623794e-01 -9.990609e-06 4.066463e-06
We can also use the moran.mc function to calculate the Moran’s I coefficient. This function uses a Monte Carlo simulation to calculate the p-value. The function is part of the spdep package.
spdep::moran.mc(x = logcounts(sfe)["KRT17",],
listw = weights_neighbourhoods,
nsim = 200)
Monte-Carlo simulation of Moran I
data: logcounts(sfe)["KRT17", ]
weights: weights_neighbourhoods
number of simulations + 1: 201
statistic = 0.64399, observed rank = 201, p-value = 0.004975
alternative hypothesis: greater
We can see both genes have a positive Moran’s I coefficient and a highly significant p-value. The expected value is \(\mathbb{E}(I) = -1/(n-1)\) which is for large \(N\) close to 0. Positive and significant values indicate clustering of similar like values. It is important to note that this could be both at the high or low end of the values. Negative values indicate clustering of alternating values, i.e. gives a measure of spatial heterogeneity. It is also important to note that the result is dependent on the neighbourhood matrix. Different neighbourhood matrices will give different results. To compare Moran’s I coefficients between different values we need to use the same neighbourhood matrix. Otherwise, we would have to rely on standardized \(z\)-scores.
Global’s Geary’s coefficient
Geary’s \(C\) is a different measure of global autocorrelation and is very closely related to Moran’s \(I\). Howver, it focuses on spatial dissimilarity. Geary’s \(C\) is defined by
\[ C = \frac{(n-1) \sum_i \sum_j w_{ij}(y_i-y_j)^2}{2\sum_i \sum_j w_{ij}\sum_i(y_i-\bar{y})^2} \]
where \(n\) is the number of locations, \(i,j\) are different locations, \(y_i\) is the value of the variable of interest for location \(i\), \(\bar{y}\) is the mean of \(y_i\) and \(w_{ij}\) is the spatial weight between locations \(i\) and \(j\). The interpretation is inversely to Moran’s \(I\). A value less than \(1\) indicates positive auto-correlation, a value more than \(1\) negative auto-correlation.
Implementation using voyager
sfe <- runUnivariate(sfe,
features = c("KRT17", "TAGLN"),
colGraphName = "knn5", nsim = 200,
type = "geary.mc")
res <- rowData(sfe)[c("KRT17", "TAGLN"),]
#value of the metric
res$geary.mc_statistic_sample01[1] 0.3563555 0.7259383
#p-value
res$geary.mc_p.value_sample01[1] 0.004975124 0.004975124
Implementation using spdep
#create nearest neighbours weights
weights_neighbourhoods <- colGraph(sfe, "knn5")
spdep::geary.test(x = logcounts(sfe)["KRT17",],
listw = weights_neighbourhoods,
randomisation = TRUE)
Geary C test under randomisation
data: logcounts(sfe)["KRT17", ]
weights: weights_neighbourhoods
Geary C statistic standard deviate = 293.94, p-value < 2.2e-16
alternative hypothesis: Expectation greater than statistic
sample estimates:
Geary C statistic Expectation Variance
3.563555e-01 1.000000e+00 4.794895e-06
spdep::geary.test(x = logcounts(sfe)["TAGLN",],
listw = weights_neighbourhoods,
randomisation = TRUE)
Geary C test under randomisation
data: logcounts(sfe)["TAGLN", ]
weights: weights_neighbourhoods
Geary C statistic standard deviate = 121.89, p-value < 2.2e-16
alternative hypothesis: Expectation greater than statistic
sample estimates:
Geary C statistic Expectation Variance
7.259383e-01 1.000000e+00 5.055704e-06
Again the value of Geary’s \(C\) indicates that the genes are spatially auto-correlated.
Local measures
Unlike global measures, that give as an overview over the entire study are local measures give us information about the statistic at each location, i.e. cell. There exist local analogs of Moran’s I and Geary’s C for which the gobal statistc counterpart can be seen as weighted sum of its respective local statistic. These coefficients are based on the spatial weights matrix and the values of the variable of interest.
Local Moran’s I coefficient
The local Moran’s I coefficient is a measure of spatial autocorrelation on each location of interest. It is defined as
\[I_i = \frac{x_i - \bar{x}}{\sum_{k=1}^n(x_k-\bar{x})^2/(n-1)} \sum_{j=1}^n w_{ij}(x_j - \bar{x})\] where the idex \(i\) refers to the location for which the measure is calculated. The interpratation is analog to the gobal Moran’s I. The value of \(I_i\) is close to \(0\) for large \(n\). A value higher than \(\mathbb{E}(I) = -1/(n-1)\) indicates spatial auto-correlation. Smaller values indicate negative auto-correlation. It is important to note that, like for the global counterpart, the value of local Moran’s I could be a result from both the high or low end of the values. Since we measure a great number of locations at the same time, we need to correct for multiple testing. We use the Benjamini-Hochberg procedure to correct for multiple testing.
Implementation using voyager
sfe <- runUnivariate(sfe,
features = c("KRT17", "TAGLN"),
type = "localmoran")
plotLocalResult(sfe, "localmoran",
features = c("KRT17", "TAGLN"), ncol = 2,
colGeometryName = "centroids")Implementation using spdep
TODO: change this impelemntation to work with gene instead of cell counts
# TODO: add weights matrix, add which sf feature to extract for plotting
#calculate local Moran's I and then correct for multiple testing using Benjamini-Hochberg correction if you want to plot p-values
localplotCell <- function(sfe, var, fun, plotvar, weights_neighbourhoods,
type){
if (type == 'expression'){
#extract the gene counts
x <- logcounts(sfe)[var,]
}
else if (type == 'feature'){
#extract the cell counts
x <- sfe[[var]]
}
else{
stop('type must be either "gene" or "cell"')
}
loc <- do.call(fun, args = list(x= x, listw = weights_neighbourhoods))
#why so ever, 'localG' has a different return structure than 'localmoran'. Thus, this conditional with different indexing
if(fun %in% c('localG')){
loc <- attr(loc, 'internals')
#extract the effect size
locEffect <- loc[,1]
#extract the p-value and adjust for multiple testing
p.val.adj <- loc[,5] |> p.adjust("BH")
}
else if(fun == 'localC_perm'){
p.val.adj <- attr(loc, 'pseudo-p')[,'Pr(z != E(Ci))']
locEffect <- loc
}
else if (fun == 'LOSH'){
locEffect <- loc[,1]
p.val.adj <- c()
}
else{
#extract the effect size
locEffect <- loc[,1]
#extract the p-value and adjust for multiple testing
p.val.adj <- loc[,5] |> p.adjust("BH")
}
#convert into a plain sf object for plotting
sf <- colGeometries(sfe)$cellSeg
sf$locEffect <- locEffect
sf$p.val.adj <- p.val.adj
return(tm_shape(sf) + tm_fill(col = plotvar))
# p <- ggplot() +
# geom_sf(data = sf, aes(fill = plotvar)) +
# scale_y_continuous(breaks = 34:36)
# return(p)
}p <- localplotCell(sfe, 'KRT17', fun = 'localmoran', plotvar = 'locEffect', weights_neighbourhoods = weights_neighbourhoods, type = 'expression')
q <- localplotCell(sfe, 'TAGLN', fun = 'localmoran', plotvar = 'locEffect', weights_neighbourhoods = weights_neighbourhoods, type = 'expression')
tmap_arrange(p,q)Local Geary’s C coefficient
Similar to local Moran’s I there is a local Geary’s C coefficient. It is defined as
\[C_i = \sum_{j=1}^n w_{ij}(z_i-z_j)^2\]
The interpretation is analog to the global Geary’s C. A value less than \(1\) indicates positive auto-correlation, a value more than \(1\) negative auto-correlation.
In this example we will not plot the local Gear’s C coefficient for gene expression but for features that are associated with the individual cells, e.g. the number oc counts or the number of genes expressed. We will use the colDataUnivariate function to calculate the local Geary’s C coefficient for these features.
Implementation using voyager
sfe <- runUnivariate(sfe,
features = c("KRT17", "TAGLN"),
type = "localmoran")
plotLocalResult(sfe, "localmoran",
features = c("KRT17", "TAGLN"), ncol = 2,
colGeometryName = "centroids")Implementation using spdep
The same is possible using spdep
p <- localplotCell(sfe, var = 'KRT17', fun = 'localmoran',
plotvar = 'locEffect', weights_neighbourhoods = weights_neighbourhoods,
type = 'expression')
q <- localplotCell(sfe, var = 'TAGLN', fun = 'localmoran',
plotvar = 'locEffect', weights_neighbourhoods = weights_neighbourhoods,
type = 'expression')
tmap_arrange(p,q)Local Getis-Ord statistic
The local Getis-Ord \(G_i\) statistic quantifies the weighted concentration of points within a radius \(d\) and in a local region \(i\).
\[ G_i(d) = \frac{\sum_{j=1}^n w_{ij}(d)x_j}{\sum_{j=1}^n x_j}, \text{s.t } j \neq i \]
There is a variant of this statistic, \(G_i^*(d)\) which is the same as \(G_i(d)\) except that the contribution when \(j=i\) is included in the term. Importantly, \(G_i(d)\) is scale-invariant but not location-invariant. That means, the subdivision into the \(n\) subregions matters for the computation of the local statistic.
Implementation using voyager
sfe <- runUnivariate(sfe,
features = c("KRT17", "TAGLN"),
type = "localG")
plotLocalResult(sfe, "localG",
features = c("KRT17", "TAGLN"), ncol = 2,
colGeometryName = "centroids")Implementation using spdep
p <- localplotCell(sfe, var = 'KRT17', fun = 'localG', plotvar = 'locEffect',
weights_neighbourhoods = weights_neighbourhoods,
type = 'expression')
q <- localplotCell(sfe, var = 'TAGLN', fun = 'localG', plotvar = 'locEffect',
weights_neighbourhoods = weights_neighbourhoods,
type = 'expression')
tmap_arrange(p,q)It is important to only consider sifnificant results. Postive values indicate clustering of high values, i.e. hot spots, negative values indicate clustering of low values, i.e. cold spots. The method does not detect outlier values because unlike in local Moran’s I there is no cross-product between \(i\) and \(j\). But unlike local Moran’I we know the type of interaction (high-high or low-low) between \(i\) and \(j\).
Local spatial heterosceadiscity (LOSH)
The local spatial heteroscedasticity (LOSH) is a measure of spatial autocorrelation that is based on the variance of the local neighbourhood. Unlike the other measures, this method does not assume homosceadistic variance over the whole tissue region. LOSH is defined as
\[H_i(d) = \frac{\sum_j w_{ij}(d)|e_j(d)|^a}{\sum_j w_{ij}(d)}\]
where \(e_j(d) = x_j - \bar{x}_i(d), j \in N(i,d)\) are the local residuals that are substracted from the local mean. The variable \(a\) handles the interpretation of the residuals. If \(a=1\), the residuals are interpreted as absolute deviations from the local mean. If \(a=2\), the residuals are interpreted as deviations from the local variance.
The LOSH should be interpreted in the combination with local Getis-Ord \(G_i^*\) statistic. The \(G_i^*\) quantifies the local mean of the variable of interest, while \(H_i\) quantifies the local variance. This table provided by Ord and Getis (2012) summarizes the interpretation of the combination of \(G_i^*\) and \(H_i\).
| high \(H_i\) | low \(H_i\) | |
|---|---|---|
| large \(\|G_i^*\|\) | A hot spot with heterogeneous local conditions | A hot spot with similar surrounding areas; the map would indicate whether the affected region is larger than the single “cell” |
| small $ |G_i^*| $ | Heterogeneous local conditions but at a low average level (an unlikely event) | Homogeneous local conditions and a low average level |
Implementation using spded
p <- localplotCell(sfe, var = 'nCounts', fun = 'LOSH', plotvar = 'locEffect',
weights_neighbourhoods = weights_neighbourhoods,
type = 'feature')
q <- localplotCell(sfe, var = 'nGenes', fun = 'LOSH', plotvar = 'locEffect',
weights_neighbourhoods = weights_neighbourhoods,
type = 'feature')
tmap_arrange(p,q)A note of caution
The locals methods presented above should be interpreted with care as we face the problem of multiple testing when calculating the local measure for each cell. Also the p-values calculated are pseudo p-value sand are calculated for each neighbor separately. Moreover, the presented methods should mainly serve as exploratory measures to identify interesting regions in the data. Multiple processes can lead to the same pattern from identifying the pattern we cannot infer the underlying process. Indication of clustering does not explain why this occurs. There can be true contagion where clustering is the result of spatial interaction and apparent contagion where clustering is the cause of spatial heterogeneity, e.g. local similarity is created by different spatial structures.
Appendix
Session info
sessionInfo()R version 4.3.1 (2023-06-16)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Monterey 12.6.1
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
time zone: Europe/Zurich
tzcode source: internal
attached base packages:
[1] stats4 stats graphics grDevices utils datasets methods
[8] base
other attached packages:
[1] stringr_1.5.0 dixon_0.0-8
[3] splancs_2.01-44 spdep_1.2-8
[5] spData_2.3.0 tmap_3.3-4
[7] scater_1.28.0 scran_1.28.2
[9] scuttle_1.10.3 SFEData_1.2.0
[11] SpatialFeatureExperiment_1.2.3 Voyager_1.2.7
[13] rgeoda_0.0.10-4 digest_0.6.33
[15] ncf_1.3-2 sf_1.0-14
[17] reshape2_1.4.4 patchwork_1.1.3
[19] STexampleData_1.8.0 ExperimentHub_2.8.1
[21] AnnotationHub_3.8.0 BiocFileCache_2.8.0
[23] dbplyr_2.3.4 RANN_2.6.1
[25] seg_0.5-7 sp_2.1-1
[27] rlang_1.1.1 ggplot2_3.4.4
[29] dplyr_1.1.3 mixR_0.2.0
[31] spatstat_3.0-6 spatstat.linnet_3.1-1
[33] spatstat.model_3.2-6 rpart_4.1.19
[35] spatstat.explore_3.2-3 nlme_3.1-162
[37] spatstat.random_3.1-6 spatstat.geom_3.2-5
[39] spatstat.data_3.0-1 SpatialExperiment_1.10.0
[41] SingleCellExperiment_1.22.0 SummarizedExperiment_1.30.2
[43] Biobase_2.60.0 GenomicRanges_1.52.1
[45] GenomeInfoDb_1.36.4 IRanges_2.34.1
[47] S4Vectors_0.38.2 BiocGenerics_0.46.0
[49] MatrixGenerics_1.12.3 matrixStats_1.0.0
loaded via a namespace (and not attached):
[1] spatstat.sparse_3.0-2 bitops_1.0-7
[3] httr_1.4.7 RColorBrewer_1.1-3
[5] tools_4.3.1 utf8_1.2.3
[7] R6_2.5.1 HDF5Array_1.28.1
[9] mgcv_1.8-42 rhdf5filters_1.12.1
[11] withr_2.5.1 gridExtra_2.3
[13] leaflet_2.2.0 leafem_0.2.3
[15] cli_3.6.1 labeling_0.4.3
[17] proxy_0.4-27 R.utils_2.12.2
[19] dichromat_2.0-0.1 scico_1.5.0
[21] limma_3.56.2 rstudioapi_0.15.0
[23] RSQLite_2.3.1 generics_0.1.3
[25] crosstalk_1.2.0 Matrix_1.5-4.1
[27] ggbeeswarm_0.7.2 fansi_1.0.5
[29] abind_1.4-5 R.methodsS3_1.8.2
[31] terra_1.7-55 lifecycle_1.0.3
[33] yaml_2.3.7 edgeR_3.42.4
[35] rhdf5_2.44.0 tmaptools_3.1-1
[37] grid_4.3.1 blob_1.2.4
[39] promises_1.2.1 dqrng_0.3.1
[41] crayon_1.5.2 lattice_0.21-8
[43] beachmat_2.16.0 KEGGREST_1.40.1
[45] magick_2.8.0 pillar_1.9.0
[47] knitr_1.44 metapod_1.7.0
[49] rjson_0.2.21 boot_1.3-28.1
[51] codetools_0.2-19 wk_0.8.0
[53] glue_1.6.2 vctrs_0.6.4
[55] png_0.1-8 gtable_0.3.4
[57] cachem_1.0.8 xfun_0.40
[59] S4Arrays_1.0.6 mime_0.12
[61] DropletUtils_1.20.0 units_0.8-4
[63] statmod_1.5.0 bluster_1.10.0
[65] interactiveDisplayBase_1.38.0 ellipsis_0.3.2
[67] bit64_4.0.5 filelock_1.0.2
[69] irlba_2.3.5.1 vipor_0.4.5
[71] KernSmooth_2.23-21 colorspace_2.1-0
[73] DBI_1.1.3 raster_3.6-26
[75] tidyselect_1.2.0 bit_4.0.5
[77] compiler_4.3.1 curl_5.1.0
[79] BiocNeighbors_1.18.0 DelayedArray_0.26.7
[81] scales_1.2.1 classInt_0.4-10
[83] rappdirs_0.3.3 goftest_1.2-3
[85] spatstat.utils_3.0-3 rmarkdown_2.25
[87] XVector_0.40.0 htmltools_0.5.6.1
[89] pkgconfig_2.0.3 base64enc_0.1-3
[91] sparseMatrixStats_1.12.2 fastmap_1.1.1
[93] htmlwidgets_1.6.2 shiny_1.7.5.1
[95] DelayedMatrixStats_1.22.6 farver_2.1.1
[97] jsonlite_1.8.7 BiocParallel_1.34.2
[99] R.oo_1.25.0 BiocSingular_1.16.0
[101] RCurl_1.98-1.12 magrittr_2.0.3
[103] GenomeInfoDbData_1.2.10 s2_1.1.4
[105] Rhdf5lib_1.22.1 munsell_0.5.0
[107] Rcpp_1.0.11 ggnewscale_0.4.9
[109] viridis_0.6.4 stringi_1.7.12
[111] leafsync_0.1.0 zlibbioc_1.46.0
[113] plyr_1.8.9 parallel_4.3.1
[115] ggrepel_0.9.4 deldir_1.0-9
[117] Biostrings_2.68.1 stars_0.6-4
[119] splines_4.3.1 tensor_1.5
[121] locfit_1.5-9.8 igraph_1.5.1
[123] ScaledMatrix_1.8.1 BiocVersion_3.17.1
[125] XML_3.99-0.14 evaluate_0.22
[127] BiocManager_1.30.22 httpuv_1.6.11
[129] purrr_1.0.2 polyclip_1.10-6
[131] scattermore_1.2 rsvd_1.0.5
[133] lwgeom_0.2-13 xtable_1.8-4
[135] e1071_1.7-13 RSpectra_0.16-1
[137] later_1.3.1 viridisLite_0.4.2
[139] class_7.3-22 tibble_3.2.1
[141] memoise_2.0.1 beeswarm_0.4.0
[143] AnnotationDbi_1.62.2 cluster_2.1.4